
package com.pig4cloud.pigx.wms.service.impl;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.pigx.wms.dto.ERPCancelDTO;
import com.pig4cloud.pigx.wms.dto.ERPSystemReturnDTO;
import com.pig4cloud.pigx.wms.dto.InStoragePageDTO;
import com.pig4cloud.pigx.wms.dto.WCSInvInDTO;
import com.pig4cloud.pigx.wms.dto.WCSInvOutDTO;
import com.pig4cloud.pigx.wms.dto.WGInStorageForPDADTO;
import com.pig4cloud.pigx.wms.entity.ERPInStorageDTO;
import com.pig4cloud.pigx.wms.entity.ERPInStorageItemDTO;
import com.pig4cloud.pigx.wms.entity.ERPInStorageTpDTO;
import com.pig4cloud.pigx.wms.entity.GoodSku;
import com.pig4cloud.pigx.wms.entity.InStorage;
import com.pig4cloud.pigx.wms.entity.InStorageItem;
import com.pig4cloud.pigx.wms.entity.InStorageTp;
import com.pig4cloud.pigx.wms.entity.OutStorage;
import com.pig4cloud.pigx.wms.entity.SLocation;
import com.pig4cloud.pigx.wms.entity.StockArea;
import com.pig4cloud.pigx.wms.entity.SubPackage;
import com.pig4cloud.pigx.wms.entity.TierConfig;
import com.pig4cloud.pigx.wms.entity.WcsWmsTrx;
import com.pig4cloud.pigx.wms.mapper.InStorageMapper;
import com.pig4cloud.pigx.wms.mapper.WcsWmsTrxMapper;
import com.pig4cloud.pigx.wms.service.GoodSkuService;
import com.pig4cloud.pigx.wms.service.InStorageItemService;
import com.pig4cloud.pigx.wms.service.InStorageService;
import com.pig4cloud.pigx.wms.service.InStorageTpService;
import com.pig4cloud.pigx.wms.service.SLocationService;
import com.pig4cloud.pigx.wms.service.StockAreaService;
import com.pig4cloud.pigx.wms.service.TierConfigService;
import com.pig4cloud.pigx.wms.service.WcsWmsTrxService;
import com.pig4cloud.pigx.wms.vo.InStorageItemVO;
import com.pig4cloud.pigx.wms.vo.InStoragePageVO;
import com.pig4cloud.pigx.wms.vo.InStorageTPVO;
import com.pig4cloud.pigx.wms.vo.PDADSInStorageDetailVO;
import com.pig4cloud.pigx.wms.vo.PDADSInStorageVO;
import com.pig4cloud.pigx.wms.vo.PDAWGInStorageDetailVO;
import com.pig4cloud.pigx.wms.vo.PDAWGInStorageVO;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.RandomUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 入库单信息
 *
 * @author gaoxin
 * @date 2021-04-13 14:48:32
 */
@Slf4j
@Service
@AllArgsConstructor
public class InStorageServiceImpl extends ServiceImpl<InStorageMapper, InStorage> implements InStorageService {

	private OutStorageServiceImpl outStorageService;

	private InStorageItemService inStorageItemService;

	private InStorageTpService inStorageTpService;

	private SLocationService sLocationService;

	private GoodSkuService goodSkuService;

	private WcsWmsTrxMapper wcsWmsTrxMapper;

	private WcsWmsTrxService wcsWmsTrxService;

	private StockAreaService stockAreaService;

	private TierConfigService tierConfigService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveALL(ERPInStorageDTO erpInStorageDTO) {

//		ERPSystemReturnDTO erpSystemReturnDTO = new ERPSystemReturnDTO();
//		erpSystemReturnDTO.setSuccess(true);
//		erpSystemReturnDTO.setMessage("ERP下发WMS请求处理成功.");

		InStorage inStorage = new InStorage();

		BeanUtils.copyProperties(erpInStorageDTO, inStorage);

		String inDateStr = erpInStorageDTO.getInDate();
		DateTimeFormatter dtFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime inDateLD = LocalDateTime.parse(inDateStr, dtFormatter);

		inStorage.setInDate(inDateLD);

		LocalDateTime timeNow = LocalDateTime.now();

		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");

		String ymd = dtf.format(timeNow);

		String sku = erpInStorageDTO.getErpInStorageItemDTOList().get(0).getSku();

		int randomInt = RandomUtil.randomInt(1000, 9999);

		String preWmsNo = "未知";

		if ("1".equals(inStorage.getInType())) {

			preWmsNo = "RKA";

		} else if ("3".equals(inStorage.getInType())) {
			preWmsNo = "RKB";

		} else if ("2".equals(inStorage.getInType())) {
			preWmsNo = "RKC";

		} else if ("4".equals(inStorage.getInType())) {
			preWmsNo = "RKD";

		} else if ("5".equals(inStorage.getInType())) {
			preWmsNo = "RKE";

		}

		String wmsNO = preWmsNo + ymd + sku + randomInt;

		inStorage.setWmsBillNo(wmsNO);

		this.save(inStorage);

		List<ERPInStorageItemDTO> erpInStorageItemDTOList = erpInStorageDTO.getErpInStorageItemDTOList();

		for (int i = 0; i < erpInStorageItemDTOList.size(); i++) {

			InStorageItem inStorageItem = new InStorageItem();

			ERPInStorageItemDTO erpInStorageItemDTO = erpInStorageItemDTOList.get(i);

			BeanUtils.copyProperties(erpInStorageItemDTO, inStorageItem);

			String productDateStr = erpInStorageItemDTO.getProductDate();
			LocalDateTime productDateLD = LocalDateTime.parse(productDateStr, dtFormatter);

			inStorageItem.setProductDate(productDateLD);

			String effDateStr = erpInStorageItemDTO.getEffDate();
			LocalDateTime effDateLD = LocalDateTime.parse(effDateStr, dtFormatter);

			inStorageItem.setEffDate(effDateLD);

			inStorageItem.setWmsBillNo(wmsNO);

			inStorageItem.setWmsItemNo(wmsNO + "_" + i);

			inStorageItemService.save(inStorageItem);

			List<ERPInStorageTpDTO> erpInStorageTpDTOList = erpInStorageItemDTO.getErpInStorageTpDTOList();

			//如果不是外购入库就保存托盘信息
			if (!"3".equals(inStorage.getInType())) {

				for (int j = 0; j < erpInStorageTpDTOList.size(); j++) {

					InStorageTp inStorageTp = new InStorageTp();

					ERPInStorageTpDTO erpInStorageTpDTO = erpInStorageTpDTOList.get(i);

					BeanUtils.copyProperties(erpInStorageTpDTO, inStorageTp);

					int itemId = inStorageItem.getInStorageItemId();

					inStorageTp.setInStorageItemId(itemId);

					inStorageTp.setSku(erpInStorageTpDTO.getSku());

					inStorageTp.setWmsBillNo(wmsNO);

					inStorageTp.setAmount(erpInStorageTpDTO.getAmount());

					inStorageTpService.save(inStorageTp);

				}
			}
		}

	}

	@Override
	public IPage<PDADSInStorageVO> pageDSInStorageForPDA(Page page, String order) {

		return baseMapper.pageDSInStorageForPDA(page, order);

	}

	@Override
	public PDADSInStorageDetailVO getDSInStorageDetailByTPForPDA(String uniqueCode) {

		return baseMapper.getDSInStorageDetailByTPForPDA(uniqueCode);

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public synchronized void postDSInStorageDetailForPDA(String fromLocation, String uniqueCode) throws Exception {
		InStorageTp inStorageTp =
				inStorageTpService.getOne(Wrappers.<InStorageTp>query().lambda()
						.eq(InStorageTp::getUniqueCode, uniqueCode).eq(InStorageTp::getStatus,"0"));

		InStorageItem inStorageItem = inStorageItemService.getOne(Wrappers.<InStorageItem>query().lambda()
				.eq(InStorageItem::getInStorageItemId, inStorageTp.getInStorageItemId()));

		InStorage inStorage = this.getOne(Wrappers.<InStorage>query().lambda()
				.eq(InStorage::getWmsBillNo, inStorageItem.getWmsBillNo()));

		//获取库区
		StockArea stockArea = getStockArea(inStorageItem,inStorage);


		//查询入库单中sku在不在畅销sku中
		GoodSku goodSku = goodSkuService.getOne(Wrappers.<GoodSku>query().lambda()
				.eq(GoodSku::getSku, inStorageItem.getSku()));

		//查询AGV库区中该电商入库单中sku所有库位信息
		List<SLocation> sLocationList =
				sLocationService.list(Wrappers.<SLocation>query().lambda().eq(SLocation::getAreaId, "2")
						.eq(SLocation::getIsUsed, "1")
						.eq(SLocation::getLocationStatus,"5")
						.eq(SLocation::getSku, inStorageItem.getSku()));
		int minAmount = 0;
		if(goodSku != null){
			minAmount = goodSku.getMinStock();
		}
		int agvSum = sLocationList.stream().mapToInt(SLocation::getStockNum).sum();
		//如果畅销sku中没有此sku或者AGV库区中该sku库存数大于畅销sku最小库存数，就从立库区找位置
		if (goodSku == null || agvSum > minAmount) {

			//从立库区找位置
			SLocation toLocation = sLocationService.getOne(Wrappers.<SLocation>query().lambda()
					.eq(SLocation::getAreaId, "1").eq(SLocation::getIsUsed, "0").eq(SLocation::getLocationStatus,"1")
					.eq(SLocation::getStockAreaNo,stockArea.getStockAreaNo())
					.eq(SLocation::getStatus, "1").orderByAsc(SLocation::getSOrder).last("limit 1"));

			if (toLocation == null) {

				throw new Exception("未找到合适电商入库的库位信息");
			}

			DSinStorageHandler(fromLocation, toLocation.getSLocationNo(), inStorage, inStorageTp);

		} else if (agvSum < minAmount) {

			//从AGV区域找库位
			SLocation toLocation = sLocationService.getOne(Wrappers.<SLocation>query().lambda()
					.eq(SLocation::getAreaId, "2").eq(SLocation::getIsUsed, "0").eq(SLocation::getLocationStatus,"1")
					.eq(SLocation::getStatus, "1").orderByAsc(SLocation::getSOrder).last("limit 1"));
			if (toLocation == null) {

				throw new Exception("未找到合适电商入库的库位信息");
			}

			DSinStorageHandler(fromLocation, toLocation.getSLocationNo(), inStorage, inStorageTp);

		}

	}

	@Override
	public IPage<PDAWGInStorageVO> pageWGInStorageForPDA(Page page, String wmsBillNo, String sort) {

		return baseMapper.pageWGInStorageForPDA(page, wmsBillNo, sort);

	}

	@Override
	public IPage<InStoragePageVO> getInStoragePageForVO(Page page, InStoragePageDTO inStoragePageDTO) {
		return baseMapper.getInStoragePageForVO(page, inStoragePageDTO);
	}

	@Override
	public List<InStorageItemVO> listItemForVO(String wmsBillNo) {
		return baseMapper.listItemForVO(wmsBillNo);
	}

	@Override
	public List<InStorageTPVO> listInStorageTP(String wmsBillNo) {
		return baseMapper.listInStorageTP(wmsBillNo);
	}

	@Override
	public List<PDAWGInStorageDetailVO> listWGInStorageDetailForPDA(String wmsBillNo, String inStorageItemId) {

		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		String username = authentication.getName();

		return baseMapper.pageWGInStorageDetailForPDA(username, wmsBillNo, inStorageItemId);

	}

	@Override
	public PDADSInStorageDetailVO getWGInStorageDetailForPDA(String wmsBillNo, String inStorageItemId) {

		return baseMapper.getWGInStorageDetailForPDA(wmsBillNo, inStorageItemId);

	}

	@Override
	public boolean cancelBill(ERPCancelDTO erpCancelDTO) {

		InStorage inStorage = this.getOne(Wrappers.<InStorage>query().lambda()
				.eq(InStorage::getInPageNo, erpCancelDTO.getPageNo()).eq(InStorage::getStatus, "0"));

		if (inStorage != null) {
            //如果找到符合条件的入库单，就把入库单置为已取消 "3"
			inStorage.setStatus("3");
            this.updateById(inStorage);
			return true;
		} else {
			//入库单如果没找到就查找出库单
			OutStorage outStorage = outStorageService.getOne(Wrappers.<OutStorage>query().lambda()
					.eq(OutStorage::getOutPageNo, erpCancelDTO.getPageNo()).eq(OutStorage::getStatus, "0"));
			if(outStorage != null){
				outStorage.setStatus("4");
				outStorageService.updateById(outStorage);
				return true;
			}else{
				//如果没找到此编号的出库单返回false
				return false;
			}
		}
	}

	@Override
	public boolean getKuangForDS(String toLocation) {

		//获取一个放置空框(托)的库位
		SLocation fromLocation = sLocationService.getOne(Wrappers.<SLocation>query().lambda()
				.eq(SLocation::getStatus, "1").eq(SLocation::getAreaId, "3").eq(SLocation::getLocationStatus, "2")
				.eq(SLocation::getIsUsed, "1").orderByAsc(SLocation::getSOrder).last("limit 1"));

		//从电商入库区找位置
//		SLocation toLocation = sLocationService.getOne(Wrappers.<SLocation>query().lambda()
//				.eq(SLocation::getAreaId, "5").eq(SLocation::getIsUsed, "0")
//				.eq(SLocation::getStatus, "1").eq(SLocation::getLocationStatus,"1")
//				.orderByAsc(SLocation::getSOrder).last("limit 1"));

		if(fromLocation == null){

			log.error("空托获取失败,无法运送空托盘...");

			return false;
		}

		//"wms调用wcs出库接口,使空框出库到指定地点:"+toLocation
		WCSInvOutDTO wcsInvOutDTO = new WCSInvOutDTO();
		String taskId = "wmstrx" + LocalDateTime.now()
				.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_MS_PATTERN));
		wcsInvOutDTO.setTaskId(taskId);
		wcsInvOutDTO.setInvOutType("7");
		wcsInvOutDTO.setOutLoc(fromLocation.getSLocationNo());
		wcsInvOutDTO.setStockNo(fromLocation.getTrayNo());
		wcsInvOutDTO.setLocDesti(toLocation);
		wcsInvOutDTO.setMemoInfo1("wms调用wcs出库接口,使空框(托)出库到指定地点:"+toLocation);


		if(!wcsWmsTrxService.handleWCSInvOut(wcsInvOutDTO)){
				throw new RuntimeException("调用WCS出库接口异常!!!");
		}

		WcsWmsTrx wcsWmsTrx = new WcsWmsTrx();
		wcsWmsTrx.setWmsTrxId(taskId);
		wcsWmsTrx.setTrxType("7");
		wcsWmsTrx.setFromLocation(fromLocation.getSLocationNo());
		wcsWmsTrx.setToLocation(toLocation);
		wcsWmsTrx.setTrayNo(fromLocation.getTrayNo());
		wcsWmsTrxMapper.insert(wcsWmsTrx);

		//把空框库位置成正在使用
		fromLocation.setIsUsed("2");
		sLocationService.updateById(fromLocation);

		return true;

	}

	@Override
	public void delForSave(String inPageNo) {

		InStorage inStorage = this.getById(inPageNo);
		this.removeById(inStorage.getInPageNo());

		List<InStorageItem> inStorageItems = inStorageItemService.list(Wrappers.<InStorageItem>query().lambda()
				.eq(InStorageItem::getWmsBillNo,inStorage.getWmsBillNo()));
		for(InStorageItem inStorageItem : inStorageItems){

			List<InStorageTp> inStorageTpList = inStorageTpService.list(Wrappers.<InStorageTp>query().lambda()
					.eq(InStorageTp::getWmsBillNo,inStorage.getWmsBillNo()));
			inStorageItemService.removeById(inStorageItem.getInStorageItemId());
			for(InStorageTp inStorageTp : inStorageTpList){

				inStorageTpService.removeById(inStorageTp.getInStorageTpId());

			}

		}

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void postWGInStorageDetailForPDA(WGInStorageForPDADTO wgInStorageForPDADTO) throws Exception{

		InStorageTp inStorageTpCheck = inStorageTpService.getOne(Wrappers.<InStorageTp>query().lambda()
				.eq(InStorageTp::getInStorageItemId, wgInStorageForPDADTO.getInStorageItemId())
				.eq(InStorageTp::getUniqueCode,wgInStorageForPDADTO.getUniqueCode()));

		if(null != inStorageTpCheck){

			throw new Exception("找到同一外购入库单提交重复托盘的情况,托盘号:"+wgInStorageForPDADTO.getUniqueCode());

		}

		InStorageItem inStorageItem = inStorageItemService.getOne(Wrappers.<InStorageItem>query().lambda()
				.eq(InStorageItem::getInStorageItemId, wgInStorageForPDADTO.getInStorageItemId()));

		InStorage inStorage = this.getOne(Wrappers.<InStorage>query().lambda()
				.eq(InStorage::getWmsBillNo, inStorageItem.getWmsBillNo()));


		StockArea stockArea = getStockArea(inStorageItem,inStorage);

			//从立库区找位置
			SLocation toLocation = sLocationService.getOne(Wrappers.<SLocation>query().lambda()
					.eq(SLocation::getAreaId, "1").eq(SLocation::getIsUsed, "0").eq(SLocation::getLocationStatus,"1")
					.eq(SLocation::getStockAreaNo,stockArea.getStockAreaNo())
					.eq(SLocation::getStatus, "1").orderByAsc(SLocation::getSOrder).last("limit 1"));

			if (toLocation == null) {

				throw new Exception("未找到合适外购入库的库位信息");
			}

		InStorageTp inStorageTp = new InStorageTp();

		int itemId = inStorageItem.getInStorageItemId();

		inStorageTp.setInStorageItemId(itemId);
		inStorageTp.setSku(inStorageItem.getSku());
		inStorageTp.setWmsBillNo(inStorageItem.getWmsBillNo());
		inStorageTp.setUniqueCode(wgInStorageForPDADTO.getUniqueCode());
		inStorageTp.setSku(wgInStorageForPDADTO.getSku());
		inStorageTp.setAmount(wgInStorageForPDADTO.getAmount());
		inStorageTp.setLocation(toLocation.getSLocationNo());
		inStorageTp.setOperator(SecurityUtils.getUser().getUsername());
		inStorageTp.setStatus("1");

		inStorageTpService.save(inStorageTp);

		WGinStorageHandler(wgInStorageForPDADTO.getFromLocation(), toLocation.getSLocationNo(), inStorage, inStorageTp);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updatetoDoneById(String inStorageNo) {
		InStorage inStorage = this.getById(inStorageNo);
		inStorage.setStatus("2");
		this.updateById(inStorage);
		log.info("原始入库单"+inStorageNo+"已更新为入库完成");

		log.info("查询"+inStorage.getInBillNumber()+"入库批次下未锁定的库区更新为锁定状态");
		List<StockArea> stockAreaList = stockAreaService.list(Wrappers.<StockArea>query().lambda()
				.eq(StockArea::getInBillNumber,inStorage.getInBillNumber()).eq(StockArea::getLockStatus,"0"));

		if(null == stockAreaList || stockAreaList.size() == 0){

			log.info("没查询到相对应的库区,无需锁定");

		}else{

			List<String> stockAreaNos = new ArrayList<>();

			for(StockArea stockArea : stockAreaList){
				log.info("查询到"+inStorage.getInBillNumber()+"入库批次下未锁定的库区:"+stockArea.getStockAreaNo());
				stockAreaNos.add(stockArea.getStockAreaNo());
			}

			//更新库区为锁定状态
			stockAreaService.update(Wrappers.<StockArea>update().lambda().set(StockArea::getLockStatus,"1")
					.in(StockArea::getStockAreaNo,stockAreaNos));
			log.info("已更新以上库区锁定状态为锁定");

		}


	}

	/**
	 * 处理电商入库
	 *
	 * @param fromLocation
	 * @param toLocation
	 */
	private void DSinStorageHandler(String fromLocation, String toLocation, InStorage inStorage,
									InStorageTp inStorageTp) {

		//调用WCS AtoB的接口  fromLocation  toLocation
		WCSInvInDTO wcsInvInDTO = new WCSInvInDTO();
		String taskId = "wmstrx" + LocalDateTime.now()
				.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_MS_PATTERN));
		wcsInvInDTO.setTaskId(taskId);
		wcsInvInDTO.setTaskSource("4");
		wcsInvInDTO.setLocatorFrom(fromLocation);
		wcsInvInDTO.setInloc(toLocation);
		wcsInvInDTO.setStockNo(inStorageTp.getUniqueCode());
		wcsInvInDTO.setMemoInfo1("wms调用wcs入库接口,电商入库");

		if(!wcsWmsTrxService.handleWCSInvIn(wcsInvInDTO)){
			throw new RuntimeException("调用WCS入库接口异常!!!");
		}

		WcsWmsTrx wcsWmsTrx = new WcsWmsTrx();
		wcsWmsTrx.setWmsTrxId(taskId);
		wcsWmsTrx.setTrxType("4");
		wcsWmsTrx.setFromLocation(fromLocation);
		wcsWmsTrx.setToLocation(toLocation);
		wcsWmsTrx.setTrayNo(inStorageTp.getUniqueCode());
		wcsWmsTrxMapper.insert(wcsWmsTrx);

		//更新目标库位为使用中
		SLocation toLocationPO = sLocationService.getById(toLocation);
		toLocationPO.setIsUsed("2");
		sLocationService.updateById(toLocationPO);

		//更新入库单为入库中
		inStorage.setStatus("1");
		this.updateById(inStorage);

		//更新入库单托盘维度信息
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		String username = authentication.getName();
		inStorageTp.setOperator(username);
		inStorageTp.setStatus("1");
		inStorageTpService.updateById(inStorageTp);
	}

	/**
	 * 处理外购入库
	 *
	 * @param fromLocation
	 * @param toLocation
	 */
	private void WGinStorageHandler(String fromLocation, String toLocation, InStorage inStorage,
									InStorageTp inStorageTp) {

		//调用WCS AtoB的接口  fromLocation  toLocation
		WCSInvInDTO wcsInvInDTO = new WCSInvInDTO();
		String taskId = "wmstrx" + LocalDateTime.now()
				.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_MS_PATTERN));
		wcsInvInDTO.setTaskId(taskId);
		wcsInvInDTO.setTaskSource("8");
		wcsInvInDTO.setLocatorFrom(fromLocation);
		wcsInvInDTO.setInloc(toLocation);
		wcsInvInDTO.setStockNo(inStorageTp.getUniqueCode());
		wcsInvInDTO.setMemoInfo1("wms调用wcs入库接口,外购入库");

		if(!wcsWmsTrxService.handleWCSInvIn(wcsInvInDTO)){
			throw new RuntimeException("调用WCS入库接口异常!!!");
		}

		WcsWmsTrx wcsWmsTrx = new WcsWmsTrx();
		wcsWmsTrx.setWmsTrxId(taskId);
		wcsWmsTrx.setTrxType("8");
		wcsWmsTrx.setFromLocation(fromLocation);
		wcsWmsTrx.setToLocation(toLocation);
		wcsWmsTrx.setTrayNo(inStorageTp.getUniqueCode());
		wcsWmsTrxMapper.insert(wcsWmsTrx);

		//更新目标库位为使用中
		SLocation toLocationPO = sLocationService.getById(toLocation);
		toLocationPO.setIsUsed("2");
		sLocationService.updateById(toLocationPO);

		//更新入库单为入库中
		inStorage.setStatus("1");
		this.updateById(inStorage);

		//更新入库单托盘维度信息
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		String username = authentication.getName();
		inStorageTp.setOperator(username);
		inStorageTp.setStatus("1");
		inStorageTpService.updateById(inStorageTp);
	}

	@Override
	public StockArea getStockArea(InStorageItem inStorageItem, InStorage instorage) throws Exception {

		//获取楼层信息
		TierConfig tierConfig = tierConfigService.getById(1);

		StockArea stockArea;
		//如果是空表示第一次使用，如果入库单此托盘inbillnumber和sku相同可以放入同一层库区
		if(null == tierConfig.getInBillNumber()
				||  (instorage.getInBillNumber().equals(tierConfig.getInBillNumber())
							 && inStorageItem.getSku().equals(tierConfig.getSku()))){

			//在当前楼层中查找库区
			StockArea stockAreaUsing = stockAreaService.getOne(Wrappers.<StockArea>query().lambda()
					.eq(StockArea::getAreaId, 1)
					.eq(StockArea::getTier, tierConfig.getCurrentTier())
					.eq(StockArea::getInBillNumber, instorage.getInBillNumber())
					.eq(StockArea::getSku,inStorageItem.getSku())
					//优先查找使用中的库区
					.eq(StockArea::getStatus,"1")
					.eq(StockArea::getLockStatus,"0")
					//查找启用的库区
					.eq(StockArea::getActivatedStatus,"1")
					.orderByAsc(StockArea::getSaOrder).last("limit 1"));

			if(null == stockAreaUsing){
				log.info("未找到使用中库区。。。wms开始查找空库区。。。");
				//如果没找到就查找空库区
				StockArea stockAreaEmpty = stockAreaService.getOne(Wrappers.<StockArea>query().lambda()
						.eq(StockArea::getAreaId, 1)
						.eq(StockArea::getTier, tierConfig.getCurrentTier())
						.eq(StockArea::getStatus,"0")
						.eq(StockArea::getLockStatus,"0")
						//查找启用的库区
						.eq(StockArea::getActivatedStatus,"1")
						.orderByAsc(StockArea::getSaOrder).last("limit 1"));

				stockArea = stockAreaEmpty;

			}else{

				log.info("找到使用中库区。stockArea:"+stockAreaUsing);
				stockArea = stockAreaUsing;

			}

			tierConfig.setCurrentTier(tierConfig.getCurrentTier());
			tierConfig.setInBillNumber(instorage.getInBillNumber());
			tierConfig.setSku(inStorageItem.getSku());
			//更新当前楼层
			tierConfigService.updateById(tierConfig);

		}else{
			int usedTier = tierConfig.getCurrentTier();
			if(usedTier == tierConfig.getEndTier()){

				usedTier = tierConfig.getStartTier();

			}else {
				usedTier = usedTier+1;
			}

			//查找空库区
			StockArea stockAreaEmpty = stockAreaService.getOne(Wrappers.<StockArea>query().lambda()
					.eq(StockArea::getAreaId, 1)
					.eq(StockArea::getTier, usedTier)
					.eq(StockArea::getStatus,"0")
					.eq(StockArea::getLockStatus,"0")
					//查找启用的库区
					.eq(StockArea::getActivatedStatus,"1")
					.orderByAsc(StockArea::getSaOrder).last("limit 1"));
			if(null == stockAreaEmpty){
				log.error("未找到空库区，wms处理失败。。。楼层："+usedTier);
				throw new Exception("未找到空库区，wms处理失败。");
			}

			stockArea = stockAreaEmpty;

			tierConfig.setCurrentTier(usedTier);
			tierConfig.setInBillNumber(instorage.getInBillNumber());
			tierConfig.setSku(inStorageItem.getSku());
			//更新当前楼层
			tierConfigService.updateById(tierConfig);

		}

		if(null == stockArea){
			log.error("未找到合适的库区。。。wms处理失败。。。");
			throw new Exception("未找到合适的库区");

		}
		//更新库区状态
		stockArea.setInBillNumber(instorage.getInBillNumber());
		stockArea.setBatchNo(inStorageItem.getBatchNo());
		stockArea.setSku(inStorageItem.getSku());
		stockArea.setStatus("1");
		stockAreaService.updateById(stockArea);

		return stockArea;
	}

	@Override
	public void inBillDone(String inBillNumber) {

		List<StockArea> stockAreaList = stockAreaService.list(Wrappers.<StockArea>query().lambda()
				.eq(StockArea::getInBillNumber,inBillNumber).ne(StockArea::getLockStatus,"0"));

		if(null == stockAreaList || stockAreaList.size() == 0){

			log.error("没找到可以锁定的库区。inBillNumber："+inBillNumber);

		}else{

			List<String> stockAreaNoList = new ArrayList<>();

			for(StockArea stockArea : stockAreaList){
				stockAreaNoList.add(stockArea.getStockAreaNo());
			}

			//更新库区为锁定状态
			stockAreaService.update(Wrappers.<StockArea>update().lambda().set(StockArea::getLockStatus,"1")
					.in(StockArea::getStockAreaNo,stockAreaNoList));

		}
	}

}
